/*
 * FSWUniCEUB - 2008
 * 
 * Este arquivo é de propriedade da Fábrica de Software do UniCEUB
 * 
 * Para mais informações entre em contato com a coordenação do
 * curso de Ciência da Computação da instituição.
 */

package br.uniceub.fsw.indicadores.facade;

import br.uniceub.fsw.arquitetura.persistencia.transacao.Transacao;
import br.uniceub.fsw.arquitetura.servico.exception.NegocioException;
import br.uniceub.fsw.indicadores.bo.IndicadorBO;
import br.uniceub.fsw.indicadores.dao.ObjetivoIndicadorDAO;
import br.uniceub.fsw.indicadores.vo.ObjetivoIndicadorVO;
import br.uniceub.fsw.indicadores.dao.ObjetivoDAO;
import br.uniceub.fsw.indicadores.vo.ObjetivoVO;
import br.uniceub.fsw.indicadores.dao.IndicadorDAO;
import br.uniceub.fsw.indicadores.vo.IndicadorVO;
import br.uniceub.fsw.indicadores.dao.PeriodicidadeDAO;
import br.uniceub.fsw.indicadores.vo.PeriodicidadeVO;
import br.uniceub.fsw.indicadores.dao.DimensaoDAO;
import br.uniceub.fsw.indicadores.vo.DimensaoVO;
import br.uniceub.fsw.util.TabelaHtml;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Facade da entidade Indicador.
 * 
 * @author Marcos Mello Nobrega Soares ra2013617/8
 */
public class IndicadorFacade {
    /**
     * Mensagem de retorno do sistema.
     */
    private String message;

    /**
     * Value object do indicador.
     */
    private IndicadorVO indicador;
    
    /**
     * Lista de Dimensões
     */
    private List<List> dimensoes;
    
    /**
     * Lista de Periodicidades
     */
    private List<List> periodicidades;
    
    /**
     * Lista de Objetivos
     */
    private List<List> objetivos;
    
    
    /**
     * Lista de Objetivos do Indicador
     */
    private List<ObjetivoIndicadorVO> objetivosIndicador;
    
    /**
     * Construtor da classe.
     */
    public IndicadorFacade() {  
        this.dimensoes = new ArrayList<List>();
        this.periodicidades = new ArrayList<List>();
        this.objetivos = new ArrayList<List>();
        
        List<String> temp;
        int i;
        
        List<DimensaoVO> dims = new DimensaoDAO().consultarPorExemplo(new DimensaoVO());        
        List<PeriodicidadeVO> periods = new PeriodicidadeDAO().consultarPorExemplo(new PeriodicidadeVO());

                
        for(i = 0; i < dims.size(); i++) {
            temp = new ArrayList<String>();
            temp.add(dims.get(i).getIdDimensao().toString());
            temp.add(dims.get(i).getNoDimensao().toString());
            this.dimensoes.add(temp);
        }
        
        for(i = 0; i < periods.size(); i++) {
            temp = new ArrayList<String>();
            temp.add(periods.get(i).getIdPeriodicidade().toString());
            temp.add(periods.get(i).getDsPeriodicidade().toString());
            this.periodicidades.add(temp);
        }      
        
        ObjetivoVO exemploObjetivo = new ObjetivoVO();
        exemploObjetivo.setStObjetivoAtivo("S");
        List<ObjetivoVO> objs = new ObjetivoDAO().consultarPorExemplo(exemploObjetivo);
        
        for(i = 0; i < objs.size(); i++) {
            temp = new ArrayList<String>();
            temp.add(objs.get(i).getIdObjetivo().toString());
            temp.add(objs.get(i).getNoObjetivo().toString());
            temp.add("N");
            this.objetivos.add(temp);
        }

    }
    
    /**
     * Getter da mensagem de retorno.
     * 
     * @return Mensagem de retorno.
     */
    public String getMessage() {
        String retorno = null;
        if(this.message == null || this.message.isEmpty()) {
            retorno = "&nbsp";
        } else {
            retorno = this.message;
        }
        return retorno;
    }
    
    /**
     * Retorna o indicador.
     * 
     * @return Objeto indicador.
     */
    public IndicadorVO getIndicador() {
        return this.indicador;
    }
    
    /**
     * Retorna os Tipos de Indicador.
     * 
     * @return Lista de Tipos de Indicador.
     */
    public List<List> getDimensoes() {
        return this.dimensoes;
    }
    
    /**
     * Retorna os Tipos de Indicador.
     * 
     * @return Lista de Tipos de Indicador.
     */
    public List<List> getPeriodicidades() {
        return this.periodicidades;
    }
    
    /**
     * Retorna os Objetivos.
     * 
     * @return Lista de Objetivos.
     */
    public List<List> getObjetivos() {
        return this.objetivos;
    }
    
    /**
     * Retorna os Objetivos.
     * 
     * @return Lista de Objetivos.
     */
    public List<ObjetivoIndicadorVO> getObjetivosIndicador() {
        return this.objetivosIndicador;
    }
     
    /**
     * Responsável por executar a operação selecionada pelo usuário.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void operacao(HttpServletRequest req, HttpServletResponse resp) {
        String oper = req.getParameter("operacao");

        if(oper != null)
        {
            if (oper.equals("consultar")) {
                this.consultar(req, resp);
            }
            if (oper.equals("incluir")) {
                this.incluir(req, resp);
            }
            if (oper.equals("alterar")) {
                this.alterar(req, resp);
            }
            if (oper.equals("excluir")) {
                this.excluir(req, resp);
            }
            if (oper.equals("confirmar")) {
                this.confirmar(req, resp);
            }
        }
    }
    
    /**
     * Consultar um indicador.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void consultar(HttpServletRequest req, HttpServletResponse resp) {
        String idIndicadorTmp = req.getParameter("idIndicador");
        
        Integer idIndicador = null;
        
        if(idIndicadorTmp == null || idIndicadorTmp.equals("")) {
            return;
        } else {
            idIndicador = Integer.parseInt(idIndicadorTmp);
        }
        
        indicador = new IndicadorDAO().consultarPorId(idIndicador);
        
        if(indicador != null) {         
            ObjetivoIndicadorVO exemplo = new ObjetivoIndicadorVO();
            
            exemplo.setCdIndicador(indicador.getIdIndicador());
            objetivosIndicador = new ObjetivoIndicadorDAO().consultarPorExemplo(new ObjetivoIndicadorVO());
            for(int i = 0; i < objetivosIndicador.size(); i++) {
                
                for(int j = 0; j < objetivos.size(); j++) {
                    try {
                        if(objetivosIndicador.get(i).getCdObjetivo().intValue() == Integer.parseInt(objetivos.get(j).get(0).toString()))
                            objetivos.get(j).set(2, "S");
                    }
                    catch(NumberFormatException e) {}
                }
            }
        }
    }

    /**
     * Incluir um indicador.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void incluir(HttpServletRequest req, HttpServletResponse resp) {
        String mensagem = "";
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

        indicador = new IndicadorVO();

        try {
            indicador.setCdDimensao(Integer.parseInt(req.getParameter("cdDimensao")));
        }
        catch (NumberFormatException e) {   
        }
        
        try {
            indicador.setCdPeriodicidade(Integer.parseInt(req.getParameter("cdPeriodicidade")));
        }
        catch (NumberFormatException e) {   
        }

        indicador.setNoIndicador(req.getParameter("noIndicador").trim());
        indicador.setDsIndicador(req.getParameter("dsIndicador").trim());
        
        indicador.setDsMetaIndicador(req.getParameter("dsMetaIndicador").trim());
        try {
            if(!req.getParameter("vlMetaIndicador").trim().isEmpty())
                indicador.setVlMetaIndicador(new Float(req.getParameter("vlMetaIndicador").trim()));
        }        
        catch (NumberFormatException e) { 
            mensagem = mensagem + "Valor da meta não é um número.<br />";
        }
        try {
            if(!req.getParameter("vlLimiteControleSuperior").trim().isEmpty())
                indicador.setVlLimiteControleSuperior(new Float(req.getParameter("vlLimiteControleSuperior").trim()));
        }        
        catch (NumberFormatException e) {
            mensagem = mensagem + "Limite superior não é um número.<br />";
        }
        try {
            if(!req.getParameter("vlLimiteControleInferior").trim().isEmpty())
                indicador.setVlLimiteControleInferior(new Float(req.getParameter("vlLimiteControleInferior").trim()));
        }        
        catch (NumberFormatException e) {
            mensagem = mensagem + "Limite inferior não é um número.<br />";
        }
        try {
            if(!req.getParameter("dtInicioCalculoIndicador").trim().isEmpty()) 
                indicador.setDtInicioCalculoIndicador(sdf.parse(req.getParameter("dtInicioCalculoIndicador").trim()));
        }        
        catch (ParseException e) {
            mensagem = mensagem + "Data de início do cálculo não é uma data existente.<br />";
        }
        try {
            if(!req.getParameter("dtValidade").trim().isEmpty()) 
                indicador.setDtValidade(sdf.parse(req.getParameter("dtValidade").trim()));
        }        
        catch (ParseException e) {
            mensagem = mensagem + "Data de validade não é uma data existente.<br />";
        }
        indicador.setDtCriacao(new Date());
        indicador.setDsFormulaIndicador(req.getParameter("dsFormulaIndicador").trim());
        indicador.setStIndicadorManual(req.getParameter("stIndicadorManual"));
        indicador.setStIndicadorAtivo(req.getParameter("stIndicadorAtivo"));
        if(indicador.getStIndicadorManual() != null && indicador.getStIndicadorManual().equals("N") && req.getParameter("noProcedimentoCalculoIndicador") != null)
            indicador.setNoProcedimentoCalculoIndicador(req.getParameter("noProcedimentoCalculoIndicador").trim());
        else
            indicador.setNoProcedimentoCalculoIndicador("");
        indicador.setDsUnidadeMedidaIndicador(req.getParameter("dsUnidadeMedidaIndicador").trim());
        
        // Marcar objetivos
        String parameter = "";
        for(int i = 0; i < objetivos.size(); i++) {
            parameter = "objetivos_" + objetivos.get(i).get(0);
            if(req.getParameter(parameter) != null && req.getParameter(parameter).equals("1"))
                objetivos.get(i).set(2, "S");
            else
                objetivos.get(i).set(2, "N");
        }
        
        try {
            new IndicadorBO().validaIndicador(indicador);
        }
        catch(NegocioException e) {
            mensagem = mensagem + e.getMessage().replace("\n","<br />");
        }
        catch(Exception e) {
            mensagem = mensagem + e.getMessage();
        }
        
        if(mensagem.equals("")) { 
            try {
                ObjetivoIndicadorVO oi = new ObjetivoIndicadorVO();
                ObjetivoIndicadorDAO oiDAO = new ObjetivoIndicadorDAO();
                
                Transacao.iniciar();
                
                new IndicadorDAO().inserir(indicador);
                
                // Criar associações
                for(int i = 0; i < objetivos.size(); i++)
                    if(objetivos.get(i).get(2).equals("S")) {
                        oi.setCdIndicador(indicador.getIdIndicador());
                        oi.setCdObjetivo(Integer.parseInt(objetivos.get(i).get(0).toString()));
                        oiDAO.inserir(oi);
                    }
                
                Transacao.efetivar();
                
                mensagem = "Indicador incluído com sucesso.";                
            } catch (Exception ex) {
                Transacao.desfazer();
                mensagem = "Problema na inclusão do indicador: " + ex.getMessage();
            }
        }
        
        this.message = mensagem;
    }

    /**
     * Alterar um indicador.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void alterar(HttpServletRequest req, HttpServletResponse resp) {
        String mensagem = "";
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        
        indicador = new IndicadorVO();
        
        try {
            indicador.setIdIndicador(Integer.parseInt(req.getParameter("idIndicador")));
        }
        catch (NumberFormatException e) {
        }

        try {
            indicador.setCdDimensao(Integer.parseInt(req.getParameter("cdDimensao")));
        }
        catch (NumberFormatException e) {   
        }
        
        try {
            indicador.setCdPeriodicidade(Integer.parseInt(req.getParameter("cdPeriodicidade")));
        }
        catch (NumberFormatException e) {   
        }

        indicador.setNoIndicador(req.getParameter("noIndicador").trim());
        indicador.setDsIndicador(req.getParameter("dsIndicador").trim());
        
        indicador.setDsMetaIndicador(req.getParameter("dsMetaIndicador").trim());
        try {
            if(!req.getParameter("vlMetaIndicador").trim().isEmpty()) 
                indicador.setVlMetaIndicador(new Float(req.getParameter("vlMetaIndicador").trim()));
        }        
        catch (NumberFormatException e) { 
            mensagem = mensagem + "Valor da meta não é um número.<br />";
        }
        try {
            if(!req.getParameter("vlLimiteControleSuperior").trim().isEmpty())
                indicador.setVlLimiteControleSuperior(new Float(req.getParameter("vlLimiteControleSuperior").trim()));
        }        
        catch (NumberFormatException e) {
            mensagem = mensagem + "Limite superior não é um número.<br />";
        }
        try {
            if(!req.getParameter("vlLimiteControleInferior").trim().isEmpty())
                indicador.setVlLimiteControleInferior(new Float(req.getParameter("vlLimiteControleInferior").trim()));
        }        
        catch (NumberFormatException e) {
            mensagem = mensagem + "Limite inferior não é um número.<br />";
        }
        try {
            if(!req.getParameter("dtInicioCalculoIndicador").trim().isEmpty()) 
                indicador.setDtInicioCalculoIndicador(sdf.parse(req.getParameter("dtInicioCalculoIndicador").trim()));
        }        
        catch (ParseException e) {
            mensagem = mensagem + "Data de início do cálculo não é uma data existente.<br />";
        }
        try {
            if(!req.getParameter("dtValidade").trim().isEmpty()) 
                indicador.setDtValidade(sdf.parse(req.getParameter("dtValidade").trim()));
        }        
        catch (ParseException e) {
            mensagem = mensagem + "Data de validade não é uma data existente.<br />";
        }

        indicador.setDsFormulaIndicador(req.getParameter("dsFormulaIndicador").trim());
        indicador.setStIndicadorManual(req.getParameter("stIndicadorManual"));
        indicador.setStIndicadorAtivo(req.getParameter("stIndicadorAtivo"));
        if(indicador.getStIndicadorManual() != null && indicador.getStIndicadorManual().equals("N") && req.getParameter("noProcedimentoCalculoIndicador") != null)
            indicador.setNoProcedimentoCalculoIndicador(req.getParameter("noProcedimentoCalculoIndicador").trim());
        else
            indicador.setNoProcedimentoCalculoIndicador("");
        indicador.setDsUnidadeMedidaIndicador(req.getParameter("dsUnidadeMedidaIndicador").trim());
        
        // Marcar objetivos
        String parameter = "";
        for(int i = 0; i < objetivos.size(); i++) {
            parameter = "objetivos_" + objetivos.get(i).get(0);
            if(req.getParameter(parameter) != null && req.getParameter(parameter).equals("1"))
                objetivos.get(i).set(2, "S");
            else
                objetivos.get(i).set(2, "N");
        }
        
        try {
            new IndicadorBO().validaIndicador(indicador);
        }
        catch(NegocioException e) {
            mensagem = mensagem + e.getMessage().replace("\n","<br />");
        }
        catch(Exception e) {
            mensagem = mensagem + e.getMessage();
        }
        
        if(mensagem.equals("")) {
            
            IndicadorDAO dao = new IndicadorDAO();
            
            try {
                new IndicadorBO().validaAlteracao(indicador);
                Transacao.iniciar();
                
                
                ObjetivoIndicadorVO oi = new ObjetivoIndicadorVO();
                ObjetivoIndicadorDAO oiDAO = new ObjetivoIndicadorDAO();
                int i;
                
                oi.setCdIndicador(indicador.getIdIndicador());
                List<ObjetivoIndicadorVO> lista = oiDAO.consultarPorExemplo(oi);
                
                // Excluir associações
                if(lista != null && lista.size() > 0) 
                    for(i = 0; i < lista.size(); i++)
                        oiDAO.excluir(lista.get(i));
                
                dao.alterar(indicador);
                
                // Recriar associações
                for(i = 0; i < objetivos.size(); i++) 
                    if(objetivos.get(i).get(2).equals("S")) {
                        oi.setCdIndicador(indicador.getIdIndicador());
                        oi.setCdObjetivo(Integer.parseInt(objetivos.get(i).get(0).toString()));
                        oiDAO.inserir(oi);
                    }
                
                Transacao.efetivar();
                
                mensagem = "Indicador alterado com sucesso.";                
            }
            catch (NegocioException ex) { 
                mensagem = ex.getMessage();
            } 
            catch (Exception ex) {
                Transacao.desfazer();
                mensagem = "Problema na alteração do indicador: " + ex.getMessage();
            }
        }
         
        this.message = mensagem;
    }

    /**
     * Excluir um indicador.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void excluir(HttpServletRequest req, HttpServletResponse resp) {        
        String mensagem = null;
                
        indicador = new IndicadorVO();
        
        try {
            indicador.setIdIndicador(Integer.parseInt(req.getParameter("idIndicador")));
        }
        catch (NumberFormatException e) {
            mensagem = "ID do indicador inválido";
        }
        
        if(mensagem == null) {
            try {
                new IndicadorBO().validaExclusão(indicador);
                Transacao.iniciar();
                
                new IndicadorDAO().excluir(indicador);
                
                Transacao.efetivar();
                mensagem = "Indicador excluído com sucesso.";
            }            
            catch (NegocioException ex) {
                mensagem = "Problema na exclusão do indicador: " + ex.getMessage();
            }
            catch (Exception ex) {
                Transacao.desfazer();
                mensagem = "Problema na exclusão do indicador: " + ex.getMessage();
            }
        }
        
        this.indicador = null;
        
        this.message = mensagem;
    }
    
    /**
     * Confirmar a exclusão do indicador.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void confirmar(HttpServletRequest req, HttpServletResponse resp) {
        String mensagem = null; 

        indicador = new IndicadorVO();
        
        try {
            indicador.setIdIndicador(Integer.parseInt(req.getParameter("idIndicador")));            
        }
        catch(NumberFormatException e) {
            indicador = null;
            mensagem = "ID do Indicador desconhecido";
        }
        
        if(indicador != null) {            
            try {
                new IndicadorBO().validaExclusão(indicador);               
            }
            catch (NegocioException ex) {
                mensagem = ex.getMessage();
                indicador = null;
            }
            catch (Exception ex) {
                mensagem = "Problemas na excludão do indicador: " + ex.getMessage();
                indicador = null;
            }
            
            if(mensagem == null) {
                indicador.setNoIndicador(req.getParameter("noIndicador"));
                indicador.setDsIndicador(req.getParameter("dsIndicador"));
            }
            
            this.message = mensagem;
        }
    }

    /**
     * Retorna uma lista de indicadores a partir de parâmetros da tela
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     * @return objeto tabela com as informações necessárias
     */
    public TabelaHtml consultarIndicadores(HttpServletRequest req, HttpServletResponse resp) {
        String nome = req.getParameter("noIndicador");
        String ativo = req.getParameter("stIndicadorAtivo");
        
        if(nome != null) {
            TabelaHtml tabela = new TabelaHtml();
            
            tabela.setCampoRetorno("idIndicador");
            
            tabela.adicionarTitulo("Id");
            tabela.adicionarTamanho(0);
            tabela.adicionarTipo("Integer");
            tabela.adicionarStatus(false);
            
            tabela.adicionarTitulo("Código");
            tabela.adicionarTamanho(0);
            tabela.adicionarTipo("Integer");
            tabela.adicionarStatus(true);

            tabela.adicionarTitulo("Nome");
            tabela.adicionarTamanho(60);
            tabela.adicionarTipo("String");
            tabela.adicionarStatus(true);
                       
            tabela.gravarCampos();
            
            // Lista de indicadores
            IndicadorVO exemplo = new IndicadorVO();
            if(ativo != null && !ativo.isEmpty())
                exemplo.setStIndicadorAtivo("S");
            List<IndicadorVO> indicadores = new IndicadorDAO().consultarPorExemploNomeOuId(exemplo, nome);
                       
            // Adiciona os valores de cada indicador nas listas de ids e nomes
            for(int i = 0; i < indicadores.size(); i++) {
                tabela.adicionarRegistro(converterVoParaString(indicadores.get(i)));
            }

            return tabela;
        }
        
        return null;
    }
    
    /**
     * Transforma os campos de um VO em uma lista de Strings
     * 
     * @return lista de strings com os valores em ordem
     */
    public List<String> converterVoParaString(IndicadorVO indicador) {
        List<String> valores = new ArrayList<String>();
        
        valores.add(indicador.getIdIndicador().toString());
        valores.add(indicador.getIdIndicador().toString());
        valores.add(indicador.getNoIndicador());
        
        return valores;
    }
}